perm filename SNAILR.SAI[AL,HE] blob
sn#241881 filedate 1976-10-13 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00006 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 file_switch and file record delcarations
C00003 00003 make_file_name, open_file, copy_file_record, clear_file_record
C00006 00004 scan_command, upper_case
C00008 00005 ! got_file (returns false for null file spec)
C00012 00006 ! execution
C00015 ENDMK
C⊗;
comment file_switch and file record delcarations;
require "[][]" delimiters;
record_class
file_switch(
string
name;
integer
octal,
decimal;
record_pointer(file_switch)
next
);
record_class
file(
integer
chn; comment channel on which file accessible;
string
name,
ext,
ppn,
device,
def_ext;
boolean
out;
integer
mode, comment OPEN type info;
eof,
brchr,
count,
in_bfrs,
out_bfrs;
record_pointer(file)
next;
record_pointer(file_switch)
switches
);
comment make_file_name, open_file, copy_file_record, clear_file_record;
string procedure make_file_name(record_pointer(file) F);
return(if length(file:name[F])=0
then null
else (file:name[F] & "." & file:ext[F] & file:ppn[F]));
boolean procedure open_file(record_pointer(file) F);
begin string file_name;
if file:chn[F] < 0 then file:chn[F] ← getchan;
if length(file:device[F])=0 then file:device[F] ← "DSK";
open(file:chn[F], file:device[F], file:mode[F], file:in_bfrs[F],
file:out_bfrs[F], file:count[F], file:brchr[F], file:eof[F]);
if file:eof[F] then
begin release(file:chn[F]); file:chn[F] ← -1; return(false) end;
file_name ← make_file_name(F);
if file:out[F]
then enter(file:chn[F], file_name, file:eof[F])
else lookup(file:chn[F], file_name, file:eof[F]);
return(¬file:eof[F]);
end;
procedure copy_file_record(record_pointer(file) dup, original);
begin
forlc field ← (chn, name, ext, ppn, device, def_ext, out, mode, eof, brchr,
count, in_bfrs, out_bfrs, next, switches)
doc [file:field[dup] ← file:field[original];] endc
end;
procedure clear_file_record(record_pointer(file) F);
begin
forlc field ← (chn, name, ext, ppn, device, def_ext)
doc [file:field[F] ← null;] endc
forlc field ← (out, mode, eof, brchr, count, in_bfrs, out_bfrs)
doc [file:field[F] ← 0;] endc
forlc field ← (next, switches)
doc [file:field[F] ← null_record;] endc
end;
comment scan_command, upper_case;
record_pointer(file) procedure scan_command(string s;
record_pointer(file) rel, lst(null_record), swap(null_record));
begin "scanner"
define
! =[comment],
tab ='11,
lf ='12,
cr ='15,
space ='40;
integer
break,
ignore_blanks_break,
pass_digits_break,
file_name_break,
ppn_break,
case_conversion;
boolean
saw_file;
record_pointer(file)
src,
F;
string procedure upper_case(string s);
begin integer temp; return(scan(s, case_conversion, temp)) end;
! got_file (returns false for null file spec);
boolean procedure got_file(reference string s; reference integer break;
record_pointer(file) F);
begin string word; record_pointer(file_switch) FS, FS1;
integer procedure ignore_blanks(reference string s);
begin integer break; scan(s, ignore_blanks_break, break); return(break) end;
string procedure filwrd;
begin ignore_blanks(s); return(scan(s, file_name_break, break)) end;
word ← filwrd; file:chn[F] ← -1; ! file has not been opened flag;
if (break=0 ∨ break=lf ∨ break=cr ∨ break="," ∨ break="←") and length(word)=0
then return(false);
if break=":" then begin file:device[F] ← word; word ← filwrd end;
file:name[F] ← word;
if break="." then file:ext[F] ← filwrd;
if break="[" then
begin
ignore_blanks(s); file:ppn[F] ← "[" & scan(s, ppn_break, break) & "]";
if break="]" then begin ignore_blanks(s); break ← lop(s) end;
end;
if break="/" or break="(" then
begin integer chr;
do begin "switches" string sign, digits;
chr ← ignore_blanks(s); sign ← null;
if chr=")" then done;
if (FS1 ← FS)=null_record
then FS ← file:switches[F] ← new_record(file_switch)
else FS ← file_switch:next[FS1] ← new_record(file_switch);
if chr="+" ∨ chr="-" then begin sign←lop(s); chr←ignore_blanks(s) end;
if "0" ≤ chr ≤ "9" then
begin
digits ← sign & scan(s, pass_digits_break, chr);
file_switch:octal[FS] ← cvo(digits);
file_switch:decimal[FS] ← cvd(digits);
sign ← null; chr ← ignore_blanks(s);
end;
if sign then file_switch:octal[FS] ← file_switch:decimal[FS]
← cvd(sign & "1");
file_switch:name[FS] ← lop(s); ignore_blanks(s);
if break="/" then chr ← lop(s); ! skip the break character;
file_switch:name[FS] ← upper_case(file_switch:name[FS]);
end "switches"
until (break="(" and chr=")") or (break≠"(" and chr≠"/");
if break="(" and chr=")" then
begin chr ← lop(s); ignore_blanks(s); chr ← lop(s) end;
break ← chr;
end;
if length(file:device[F])=0 then file:device[F] ← "DSK";
return(true)
end;
! execution;
setbreak(
ignore_blanks_break ← getbreak, space & tab, cr, "XRK");
setbreak(
pass_digits_break ← getbreak, "0123456789", cr, "XRK");
setbreak(
file_name_break ← getbreak, "!←(/[:.," & lf, cr, "ISK");
setbreak(
ppn_break ← getbreak, "!←(/]" & lf, cr, "ISK");
setbreak(
case_conversion ← getbreak, null, null, "ISK");
saw_file ← got_file(s, break, F ← new_record(file)); file:out[F] ← true;
if break="!"
then usererr(0, 0, "SNAILR: ""!"" not yet implemented.")
else if ¬(break="," or break="←")
then usererr(0, 0, "SNAILR: command line error")
else
begin
if ¬saw_file then file:eof[F] ← true; ! indicates file not seen;
if rel≠null_record then copy_file_record(rel, F)
end;
if lst≠null_record then file:eof[lst] ← true;
if break="," and (saw_file ← got_file(s, break, F ← new_record(file))) then
begin
file:out[F] ← true;
if lst≠null_record then
begin
if saw_file then file:eof[F] ← false;
copy_file_record(lst, F)
end
end;
if break≠"←" then usererr(0, 0, "SNAILR: command line error");
src ← null_record;
begin "source loop" record_pointer(file) F1;
do begin
if ¬got_file(s, break, F ← new_record(file)) then file:eof[F] ← false;
if src=null_record
then src ← F1 ← F
else begin file:next[F1] ← F; F1 ← F end;
if ¬(break="," ∨ break=cr ∨ break=lf ∨ break=0)
then usererr(0, 0, "SNAILR: command line error");
end
until break=lf ∨ break=cr ∨ break=0;
end "source loop";
relbreak(ignore_blanks_break);
relbreak(pass_digits_break);
relbreak(file_name_break);
relbreak(ppn_break);
relbreak(case_conversion);
return(src);
end "scanner";
require unstack_delimiters;